(ns acst.routes.auth
  (:use acst.config.error-config
        acst.config.success-config
        acst.utils.handle-exp)
  (:require [noir.util.crypt :as crypt]
            [noir.session :as session]
            [noir.validation :as vali]
            [selmer.parser :as parser]
            [ring.middleware.anti-forgery :as af]
            [compojure.core :refer :all]
            [acst.models.users :as users :refer :all]
            [clojure.data.json :as json]))


(defn error-item [[error]]
  [{:error error}])

(defn valid-register? [username password]
  (vali/rule (vali/has-value? username) [:username "你没写名字"])
  (vali/rule (vali/min-length? username 4) [:username "你名字不够长"])
  (vali/rule (nil? (try (re-find #"[\<\>\"\\\&\s]" username) (catch NullPointerException e nil))) [:username "用户名含有非法字符"])
  (vali/rule (vali/min-length? password 5) [:password "你的密码太短了"])
  (not (vali/errors? :username :password)))

(defn registration []
  (parser/render-file
    "registration.html"
    {:value af/*anti-forgery-token*}))

(defn handler-restration [username password]
  (-> (if (valid-register? username password)
        (let [result (users/register! username (crypt/encrypt password))]
          (if (get-error result)
             result
             (do
               (set-user-session! (:username result) (:user_id result))
               (:register-success users-result))))
        (or (vali/on-error :username error-item)
            (vali/on-error :password error-item)))
      (json/write-str)))

(defn login []
  (parser/render-file
    "login.html"
    {:value af/*anti-forgery-token*}))


(defn handle-login [username password]
  (->
    (let [{pass-hash :password user_id :user_id} (first (users/find-password username))]
      (if (and (not (nil? pass-hash)) (crypt/compare password pass-hash))
        (do
          (set-user-session! username user_id)
          (:login-success users-result))
        (:password-error users-error)))
    (json/write-str)))


(defn logout []
  (rm-user-session!)
  (json/write-str (:logout-success users-result)))



(defroutes auth-routes
           (context "/api/auth" []
             (GET "/register" [] (registration))
             (POST "/register" [username password] (handler-restration username password))
             (GET "/login" [] (login))
             (POST "/login" [username password] (handle-login username password))
             (GET "/logout" []  (logout))))
